package com.googlecode.gwt.test.plugin.editors;


import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;

import com.googlecode.gwt.test.plugin.editors.WordTracker.Proposal;

public class GWTCsvContentAssistProcessor implements IContentAssistProcessor {
	private String lastError = null;
	private IContextInformationValidator contextInfoValidator;
	private WordTracker wordTracker;
	private IProject currentProject;

	public GWTCsvContentAssistProcessor(KeyWords keyWords, IProject currentProject) {
		wordTracker = new WordTracker(keyWords);
		this.currentProject = currentProject;
	}

	public ICompletionProposal[] computeCompletionProposals(ITextViewer textViewer, int documentOffset) {
		IDocument document = textViewer.getDocument();
		int currOffset = documentOffset - 1;

		try {
			String currWord = "";
			char currChar;
			while (currOffset > 0 && !Character.isWhitespace(currChar = document.getChar(currOffset))) {
				currWord = currChar + currWord;
				currOffset--;
			}

			List<Proposal> suggestions = wordTracker.suggest(currWord);
			ICompletionProposal[] proposals = null;
			if (suggestions.size() > 0) {
				proposals = buildProposals(suggestions, currWord, documentOffset - currWord.length());
				lastError = null;
			}
			return proposals;
		} catch (BadLocationException e) {
			e.printStackTrace();
			lastError = e.getMessage();

		} catch (Exception e) {
			e.printStackTrace();
			lastError = e.getMessage();
		}
		return null;
	}

	private ICompletionProposal[] buildProposals(List<Proposal> suggestions, String replacedWord, int offset) throws JavaModelException {
		ICompletionProposal[] proposals = new ICompletionProposal[suggestions.size()];
		int index = 0;
		for (Iterator<Proposal> i = suggestions.iterator(); i.hasNext();) {
			Proposal currSuggestion = (Proposal) i.next();
			CompletionProposal cp = new CompletionProposal(currSuggestion.getReplacementText(), offset, replacedWord.length(), currSuggestion
					.getReplacementText().length(), null, currSuggestion.getDisplayedText(), null, getAdditionalPropositionInfo(currSuggestion));
			proposals[index] = cp;
			index++;
		}
		return proposals;
	}

	private String getAdditionalPropositionInfo(Proposal currSuggestion) throws JavaModelException {
		String additionalInfo = "Coming soon keyword description" + currSuggestion.getDisplayedText();
		String tmp = this.updateAdditionalInfoCustomKeyWord(currSuggestion.displayedText);
		if (tmp != null) {
			additionalInfo = tmp;
		} else {
			tmp = this.updateAdditionalInfoMacro(currSuggestion.getDisplayedText());
			if (tmp != null) {
				additionalInfo = tmp;
			}
		}
		return additionalInfo;
	}

	private String updateAdditionalInfoMacro(String displayedText) {
		String additionalInfo = ProjectPluginProperty.getInstance().getMacroResource(this.currentProject).getMacroComment(displayedText);
		return additionalInfo;
	}

	private String updateAdditionalInfoCustomKeyWord(String word) throws JavaModelException {
		String additionalInfo = null;
		IType type = ProjectPluginProperty.getInstance().getCustomKeyWordsResource(this.currentProject).getType(word);
		if (type != null) {
			IMethod method = getMethodByName(type, word);
			String javadoc = null;
			if (method != null && method.getSource() != null) {
				javadoc = method.getSource().substring(0, method.getJavadocRange() == null ? 0 : method.getJavadocRange().getLength());
			}
			if (javadoc == null || javadoc.length() == 0) {
				javadoc = method.getAttachedJavadoc(null);
			}
			if (javadoc != null)
				additionalInfo = javadoc;
		}
		return additionalInfo;
	}

	private IMethod getMethodByName(IType type, String word) throws JavaModelException {
		for (IMethod m : type.getMethods()) {
			if (m.getElementName().equals(word))
				return m;
		}
		return null;
	}

	public IContextInformation[] computeContextInformation(ITextViewer textViewer, int documentOffset) {
		lastError = "No Context Information available";
		return null;
	}

	public char[] getCompletionProposalAutoActivationCharacters() {
		//we always wait for the user to explicitly trigger completion
		return null;
	}

	public char[] getContextInformationAutoActivationCharacters() {
		//we have no context information
		return null;
	}

	@Override
	public IContextInformationValidator getContextInformationValidator() {
		return contextInfoValidator;
	}

	@Override
	public String getErrorMessage() {
		System.out.println("[" + lastError + "]");
		return lastError;
	}

}
